/* igrs-server.c */

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>

#include <unistd.h>

#include "igrs-server.h"
#include "igrs.h"
#include "ip.h"
#include "udp.h"
#include "dump.h"

int igrs_server_open(IGRS_SERVER *srv)
{
  srv->sock = udp_open(1900);
  if (srv->sock < 0) {
    dump_msg("Error: can't create IGRS UDP server on port 1900.\n");
    return -1;
  }
  if (udp_register_multicast(srv->sock, IP_MAKE(239,255,255,250)) < 0) {
    dump_msg("Error: can't setup IGRS UDP multicast.\n");
    return -1;
  }
  return 0;
}

void igrs_server_close(IGRS_SERVER *srv)
{
  udp_close(srv->sock);
}

void igrs_server_run(IGRS_SERVER *srv)
{
  int len, reply_len;
  net_u32 ip, listener_ip;
  int port, listener_port;
  char buf[4096], *reply;

  while (42) {
    // read request
    len = udp_recv(srv->sock, buf, sizeof(buf), &ip, &port);
    if (len < 0) {
      if (errno != EINTR) {
	dump_msg("** ERROR: can't read IGRS request.\n");
	usleep(10000000);
      }
      continue;
    }

    // build reply
    listener_ip = ip_guess_local_address(ip);
    listener_port = 3880;
    reply_len = igrs_build_reply(buf, len, listener_ip, listener_port, &reply, &ip, &port);
    if (reply_len < 0)
      continue;

    // send reply
    dump_msg("-> IGRS request from %d.%d.%d.%d:%d -> using listener at %d.%d.%d.%d:%d\n",
	     (ip>>24)&0xff, (ip>>16)&0xff, (ip>>8)&0xff, ip&0xff, port,
	     (listener_ip>>24)&0xff, (listener_ip>>16)&0xff, (listener_ip>>8)&0xff, listener_ip&0xff, listener_port);
    dump_msg("-> IGRS replying to %d.%d.%d.%d:%d\n",
	   (ip>>24)&0xff, (ip>>16)&0xff, (ip>>8)&0xff, ip&0xff, port);
    len = udp_send(srv->sock, reply, reply_len, ip, port);
    free(reply);
    if (len != reply_len) {
      dump_msg("** ERROR sending IGRS reply\n");
      continue;
    }
  }
}
